package pres.seanlang.utility;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 *  Json工具
 *
 * @author SeanLang
 */
public class JsonUtils {
    private static final String TAG = "JsonUtils";

    protected JsonUtils() { throw new UnsupportedOperationException("can't instance..."); }

    /**
     *  解析json字符串并返回JSONObject
     * @param json
     * @return
     */
    public static JSONObject parseObject(String json) {
        JSONObject object = null;
        if(!StringUtils.isEmpty(json)) {
            try {
                object = new JSONObject(json);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return object;
    }

    /**
     *  解析json字符串并返回JSONArray
     * @param json
     * @return
     */
    public static JSONArray parseArray(String json) {
        JSONArray array = null;
        if(!StringUtils.isEmpty(json)) {
            try {
                array = new JSONArray(json);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return array;
    }

    /**
     *   获取JSONObject中的string值
     * @param object        目标JSONObject
     * @param name          属性名
     * @param defValue      默认值
     * @return
     */
    public static String getString(JSONObject object, String name, String... defValue) {
        String value = defValue.length > 0 ? defValue[0] : null;
        if(object != null && !StringUtils.isEmpty(name)) {
            try {
                value = object.getString(name);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return value;
    }

    /**
     *  获取JSONObject中的int值
     * @param object    目标JSONObject
     * @param name      属性名
     * @param defValue  默认值
     * @return
     */
    public static int getInt(JSONObject object, String name, int... defValue) {
        int value = defValue.length > 0 ? defValue[0] : 0;
        if(object != null && !StringUtils.isEmpty(name)) {
            try {
                value = object.getInt(name);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return value;
    }

    /**
     *  获取JSONObject中的long值
     * @param object    目标JSONObject
     * @param name      属性名
     * @param defValue  默认值
     * @return
     */
    public static long getLong(JSONObject object, String name, long... defValue) {
        long value = defValue.length > 0 ? defValue[0] : 0L;
        if(object != null && !StringUtils.isEmpty(name)) {
            try {
                value = object.getLong(name);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return value;
    }

    /**
     *  获取JSONObject中的double值
     * @param object    目标JSONObject
     * @param name      属性名
     * @param defValue  默认值
     * @return
     */
    public static double getDouble(JSONObject object, String name, double... defValue) {
        double value = defValue.length > 0 ? defValue[0] : 0.0f;
        if(object != null && !StringUtils.isEmpty(name)) {
            try {
                value = object.getDouble(name);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return value;
    }

    /**
     *  获取JSONObject中的boolean值
     * @param object    目标JSONObject
     * @param name      属性名
     * @return
     */
    public static boolean getBoolean(JSONObject object, String name) {
        boolean value = false;
        if(object != null && !StringUtils.isEmpty(name)) {
            try {
                value = object.getBoolean(name);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return value;
    }

    /**
     *  获取JSONObject中的JSONObject值
     * @param object    目标JSONObject
     * @param name      属性名
     * @return
     */
    public static JSONObject getJSONObject(JSONObject object, String name) {
        if(object != null && !StringUtils.isEmpty(name)) {
            try {
                return object.getJSONObject(name);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    /**
     *  获取JSONObject中的JSONArray值
     * @param object    目标JSONObject
     * @param name      属性名
     * @return
     */
    public static JSONArray getJSONArray(JSONObject object, String name) {
        if(object != null && !StringUtils.isEmpty(name)) {
            try {
                return object.getJSONArray(name);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    /**
     *  从JSONArray中获取String值
     * @param array     目标JSONArray
     * @param index     数组index, JSONArray的大小可以通过{@link JSONArray#length()}获取
     * @return
     */
    public static String getString(JSONArray array, int index) {
        if(array != null && index < array.length() && index >= 0) {
            try {
                return array.getString(index);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    /**
     *  从JSONArray中获取int值
     * @param array     目标JSONArray
     * @param index     数组index
     * @return
     */
    public static int getInt(JSONArray array, int index) {
        if(array != null && index < array.length() && index >= 0) {
            try {
                return array.getInt(index);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return 0;
    }

    /**
     *  从JSONArray中获取long值
     * @param array     目标JSONArray
     * @param index     数组index
     * @return
     */
    public static long getLong(JSONArray array, int index) {
        if(array != null && index < array.length() && index >= 0) {
            try {
                return array.getLong(index);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return 0L;
    }

    /**
     *  从JSONArray中获取double值
     * @param array     目标JSONArray
     * @param index     数组index
     * @return
     */
    public static double getDouble(JSONArray array, int index) {
        if(array != null && index < array.length() && index >= 0) {
            try {
                return array.getDouble(index);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return 0.0f;
    }

    /**
     *  从JSONArray中获取boolean值
     * @param array     目标JSONArray
     * @param index     array脚标
     * @return
     */
    public static boolean getBoolean(JSONArray array, int index) {
        if(array != null && index < array.length() && index >= 0) {
            try {
                return array.getBoolean(index);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return false;
    }

    /**
     *  从JSONArray中获取JSONObject
     * @param array     目标JSONArray
     * @param index     array脚标
     * @return
     */
    public static JSONObject getJSONObject(JSONArray array, int index) {
        if(array != null && index < array.length() && index >= 0) {
            try {
                return array.getJSONObject(index);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    /**
     *  从JSONArray中获取JSONArray
     * @param array     目标JSONArray
     * @param index     array脚标
     * @return
     */
    public static JSONArray getJSONArray(JSONArray array, int index) {
        if(array != null && index < array.length() && index >= 0) {
            try {
                return array.getJSONArray(index);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    /**
     *  将JSONObject转换转换为map, 注意该方法不进行深度转换.
     * @param object
     * @return
     */
    public static Map<String, String> toMap(JSONObject object) {
        if(object == null) {
            return null;
        } else {
            Map<String, String> map = new HashMap<>();
            if(object.length() > 0) {
                Iterator<String> keys = object.keys();
                while(keys.hasNext()) {
                    String name = keys.next();
                    map.put(name, getString(object, name));
                }
            }

            return map;
        }
    }

    /**
     *  从json字符串中提取int值 <br>
     *      提示:不支持子对象的内容获取
     * @param json  json字符串
     * @param name  属性名
     * @return
     */
    public static int getInt(String json, String name) {
        JSONObject object = parseObject(json);
        if(object == null) return -1;
        return getInt(object, name);
    }

    /**
     *  从json字符串中提取long值 <br>
     *      提示:不支持子对象的内容获取
     * @param json  json字符串
     * @param name  属性名
     * @return
     */
    public static long getLong(String json, String name) {
        JSONObject object = parseObject(json);
        if(object == null) return -1;
        return getLong(object, name);
    }

    /**
     *  从json字符串中提取double值 <br>
     *      提示:不支持子对象的内容获取
     * @param json  json字符串
     * @param name  属性名
     * @return
     */
    public static double getDouble(String json, String name) {
        JSONObject object = parseObject(json);
        if(object == null) return 0.0f;
        return getDouble(object, name);
    }

    /**
     *  从json字符串中提取boolean值 <br>
     *      提示:不支持子对象的内容获取
     * @param json  json字符串
     * @param name  属性名
     * @return
     */
    public static boolean getBoolean(String json, String name) {
        JSONObject object = parseObject(json);
        if(object == null) return false;
        return getBoolean(json, name);
    }

    /**
     *  从json字符串中提取String值 <br>
     *      提示:不支持子对象的内容获取
     * @param json  json字符串
     * @param name  属性名
     * @return
     */
    public static String getString(String json, String name) {
        JSONObject object = parseObject(json);
        if(object == null) return null;
        return getString(object, name);
    }

//    /**
//     *  获取JSONObject操作的包装
//     */
//    public interface Object {
//        /** 获取int */
//        int getInt(String name);
//        /** 获取long */
//        long getLong(String name);
//        /** 获取double */
//        double getDouble(String name);
//        /** 获取boolean */
//        boolean getBoolean(String name);
//        /** 获取String */
//        String getString(String name);
//        /** 获取JSONObject */
//        Object getObject(String name);
//        /** 获取JSONArray */
//        Array getArray(String name);
//    }
//
//    /**
//     *  获取JSONArray操作的包装
//     */
//    public interface Array {
//        /** 获取int值 */
//        int getInt(int index);
//        /** 获取long值 */
//        long getLong(int index);
//        /** 获取double值 */
//        double getDouble(int index);
//        /** 获取boolean值 */
//        boolean getBoolean(int index);
//        /** 获取String值 */
//        String getString(int index);
//        /** 获取JSONObject值 */
//        Object getObject(int index);
//        /** 获取JSONArray值 */
//        Array getArray(int index);
//        /** 获取JSONArray的大小 */
//        int getSize();
//    }

//    private static class ObjectWrapper implements Object {
//        private JSONObject mJSONObject;
//
//        ObjectWrapper(JSONObject object) {
//            this.mJSONObject = object;
//        }
//
//        @Override
//        public int getInt(String name) {
//            return JsonUtils.getInt(mJSONObject, name);
//        }
//
//        @Override
//        public long getLong(String name) {
//            return JsonUtils.getLong(mJSONObject, name);
//        }
//
//        @Override
//        public double getDouble(String name) {
//            return JsonUtils.getDouble(mJSONObject, name);
//        }
//
//        @Override
//        public boolean getBoolean(String name) {
//            return JsonUtils.getBoolean(mJSONObject, name);
//        }
//
//        @Override
//        public String getString(String name) {
//            return JsonUtils.getString(mJSONObject, name);
//        }
//
//        @Override
//        public Object getObject(String name) {
//            JSONObject object = JsonUtils.getJSONObject(mJSONObject, name);
//            return object != null ? new ObjectWrapper(object) : null;
//        }
//
//        @Override
//        public Array getArray(String name) {
//            JSONArray array = JsonUtils.getJSONArray(mJSONObject, name);
//            return array != null ? new ArrayWrapper(array) : null;
//        }
//    }
//
//    private static class ArrayWrapper implements Array {
//        private JSONArray mJSONArray;
//
//        ArrayWrapper(JSONArray array) {
//            this.mJSONArray = array;
//        }
//
//        @Override
//        public int getInt(int index) {
//            return JsonUtils.getInt(mJSONArray, index);
//        }
//
//        @Override
//        public long getLong(int index) {
//            return JsonUtils.getLong(mJSONArray, index);
//        }
//
//        @Override
//        public double getDouble(int index) {
//            return JsonUtils.getDouble(mJSONArray, index);
//        }
//
//        @Override
//        public boolean getBoolean(int index) {
//            return JsonUtils.getBoolean(mJSONArray, index);
//        }
//
//        @Override
//        public String getString(int index) {
//            return JsonUtils.getString(mJSONArray, index);
//        }
//
//        @Override
//        public Object getObject(int index) {
//            JSONObject object = getJSONObject(mJSONArray, index);
//            return object != null ? new ObjectWrapper(object) : null;
//        }
//
//        @Override
//        public Array getArray(int index) {
//            JSONArray array = getJSONArray(mJSONArray, index);
//            return array != null ? new ArrayWrapper(array) : null;
//        }
//
//        @Override
//        public int getSize() {
//            return mJSONArray.length();
//        }
//    }

    /**
     *  JSONObject/JSONArray操作包装
     */
    public interface WObject {
        /** 获取关于JSONObject的int */
        int getInt(String name);
        /** 获取关于JSONObject的long */
        long getLong(String name);
        /** 获取关于JSONObject的double */
        double getDouble(String name);
        /** 获取关于JSONObject的boolean */
        boolean getBoolean(String name);
        /** 获取关于JSONObject的String */
        String getString(String name);
        /** 获取关于JSONObject的JSONObject或者JSONArray */
        WObject getObject(String name);

        boolean isArray();
        /** 获取关于JSONArray的int值 */
        int getInt(int index);
        /** 获取关于JSONArray的long值 */
        long getLong(int index);
        /** 获取关于JSONArray的double值 */
        double getDouble(int index);
        /** 获取关于JSONArray的boolean值 */
        boolean getBoolean(int index);
        /** 获取关于JSONArray的String值 */
        String getString(int index);
        /** 获取关于JSONArray的JSONObject或者JSONArray */
        WObject getObject(int index);
        /** 获取关于JSONArray大小 */
        int getSize();
    }

    private static class WObjectImpl implements WObject {
        private JSONObject mJSONObject;
        private JSONArray mJSONArray;

        WObjectImpl(JSONObject object) {
            this.mJSONObject = object;
        }

        WObjectImpl(JSONArray array) {
            this.mJSONArray = array;
        }

        @Override
        public int getInt(String name) {
            if(mJSONObject != null) {
                return JsonUtils.getInt(mJSONObject, name);
            } else {
                return 0;
            }
        }

        @Override
        public long getLong(String name) {
            if(mJSONObject != null) {
                return JsonUtils.getLong(mJSONObject, name);
            } else {
                return 0;
            }
        }

        @Override
        public double getDouble(String name) {
            if(mJSONObject != null) {
                return JsonUtils.getDouble(mJSONObject, name);
            } else {
                return 0.0f;
            }
        }

        @Override
        public boolean getBoolean(String name) {
            if(mJSONObject != null) {
                return JsonUtils.getBoolean(mJSONObject, name);
            } else {
                return false;
            }
        }

        @Override
        public String getString(String name) {
            if(mJSONObject != null) {
                return JsonUtils.getString(mJSONObject, name);
            } else {
                return null;
            }
        }

        @Override
        public WObject getObject(String name) {
            if(mJSONObject != null) {
                //return JsonUtils.getInt(mJSONObject, name);
                JSONObject object = getJSONObject(mJSONObject, name);
                if(object != null) return new WObjectImpl(object);
                JSONArray array = getJSONArray(mJSONObject, name);
                if(array != null) return new WObjectImpl(array);
            }

            return null;
        }

        @Override
        public boolean isArray() {
            return mJSONObject == null ? true : false;
        }

        @Override
        public int getInt(int index) {
            if(mJSONArray != null) {
                return JsonUtils.getInt(mJSONArray, index);
            } else {
                return 0;
            }
        }

        @Override
        public long getLong(int index) {
            if(mJSONArray != null) {
                return JsonUtils.getLong(mJSONArray, index);
            } else {
                return 0;
            }
        }

        @Override
        public double getDouble(int index) {
            if(mJSONArray != null) {
                return JsonUtils.getDouble(mJSONArray, index);
            } else {
                return 0;
            }
        }

        @Override
        public boolean getBoolean(int index) {
            if(mJSONArray != null) {
                return JsonUtils.getBoolean(mJSONArray, index);
            } else {
                return false;
            }
        }

        @Override
        public String getString(int index) {
            if(mJSONArray != null) {
                return JsonUtils.getString(mJSONArray, index);
            } else {
                return null;
            }
        }

        @Override
        public int getSize() {
            if(mJSONArray != null) {
                return mJSONArray.length();
            } else {
                return 0;
            }
        }

        @Override
        public WObject getObject(int index) {
            if(mJSONArray != null) {
                JSONObject object = getJSONObject(mJSONArray, index);
                if(object != null) return new WObjectImpl(object);
                JSONArray array = getJSONArray(mJSONArray, index);
                if(array != null) return new WObjectImpl(array);
            }

            return null;
        }
    }

    /**
     *  解析json, 并返回WObject实例
     * @param json
     * @return
     */
    public static WObject parse(String json) {
        JSONObject object = parseObject(json);
        if(object != null) return new WObjectImpl(object);
        JSONArray array = parseArray(json);
        if(array != null) return new WObjectImpl(array);

        return null;
    }
}
